package info.macnana.online.jwt.filter;

import info.macnana.online.jwt.helper.JwtHelper;
import info.macnana.online.jwt.model.JsonWebTokenAuthentication;
import info.macnana.online.jwt.model.JwtUserFactory;
import info.macnana.online.user.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Component;

/**
 * author: zhengheng
 * github: https://github.com/macnana777
 * email: 517862340@qq.com
 * <p>
 * Date: 2017-08-10 11:00
 * Description:
 * 读取被转换为Spring Authentication的头部信息对象，名称为PreAuthenticatedAuthenticationToken，
 * 授权提供者读取这个记号，然后验证它，然后转换为我们自己的定制授权对象，就是把header里的token转化成我们自己的授权对象。
 * 然后把解析之后的对象返回给Spring Security，这里就相当于完成了token->session的转换。
 * Copyright(©) 2017 by zhengheng.
 */
@Component
public class JWTAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private JwtHelper jwtHelper;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Authentication authenticatedUser = null;
        if (authentication.getClass()
                .isAssignableFrom(PreAuthenticatedAuthenticationToken.class)
                //tokenHeader
                && authentication.getPrincipal() != null) {
            String tokenHeader = (String) authentication.getPrincipal();
            UserDetails userDetails = parseToken(tokenHeader);
            if (userDetails != null) {
                authenticatedUser = new JsonWebTokenAuthentication(userDetails, tokenHeader);
            }
            else {
                throw new BadCredentialsException("认证失败");
            }
        } else {
            // It is already a JsonWebTokenAuthentication
            authenticatedUser = authentication;
        }
        return authenticatedUser;
    }

    private UserDetails parseToken(String tokenHeader) {
        UserDetails principal = null;
        User user = jwtHelper.validateToken(tokenHeader);
        if (user != null) {
            principal = JwtUserFactory.create(user);
        }
        return principal;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return
                authentication.isAssignableFrom(
                        PreAuthenticatedAuthenticationToken.class) ||
                        authentication.isAssignableFrom(
                                JsonWebTokenAuthentication.class);
    }
}
